﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading;

namespace common
{
  public class WxPayHelper : DelegatingHandler
  {
    // 使用方法
    // HttpClient client = new HttpClient(new HttpHandler("{商户号}", "{商户证书序列号}"));
    // ...
    // var response = client.GetAsync("https://api.mch.weixin.qq.com/v3/certificates");

    private readonly string merchantId;
    private readonly string serialNo;

    public WxPayHelper(string merchantId, string merchantSerialNo)
    {
      InnerHandler = new HttpClientHandler();
      this.merchantId = merchantId;
      this.serialNo = merchantSerialNo;
    }

    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
      var auth = await BuildAuthAsync(request);
      string value = $"WECHATPAY2-SHA256-RSA2048 {auth}";
      request.Headers.Add("Authorization", value);

      return await base.SendAsync(request, cancellationToken);
    }

    protected async Task<string> BuildAuthAsync(HttpRequestMessage request)
    {
      string method = request.Method.ToString();
      string body = "";
      if (method == "POST" || method == "PUT" || method == "PATCH")
      {
        var content = request.Content;
        body = await content.ReadAsStringAsync();
      }

      string uri = request.RequestUri.PathAndQuery;
      var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
      string nonce = Path.GetRandomFileName();
      nonce = "EOIRUEOHHHFGIUAWEQWE";

      string message = $"{method}\n{uri}\n{timestamp}\n{nonce}\n{body}\n";
      string signature = Sign(message);
      return $"mchid=\"{merchantId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{serialNo}\",signature=\"{signature}\"";
    }

    protected string Sign(string message)
    {
      // NOTE： 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY-----
      //        亦不包括结尾的-----END PRIVATE KEY-----
      string privateKey = @"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCkPZrq+/SaqpzOxWhZyC5bSoX2YWAFJibBvI0CHsXTnqYIjPfJlGpkrpQBZ0C54soTXRzfGWbQPXJveZcN7+QL9XSzstY4phv2xExqOtoTlzG9NvO5h7Gy1n6GnHbBIkcwnbv0XBDEFB99Js1tnLHGAOjpU7eaqlUhp0qIkpQIWo7P0Ez6dxNFtFHDeBcql2uKMf4NxDnNTVEu/u1CAXS1Z5ceJFsLFJMDU4g9Rcnn3PG1tG/airtVUfBv8URU4nEjSpmutgPoBAIbqv3JZfpjh74t8cYHa5rpqpbu2hvraRdozV+f8al5CSsc/UhiomorB8jTbd71Q42t8DVHC625AgMBAAECggEANuaM6W2tdyH+5rNgTVq3/DYuD4y/PxlgrTQs4n+M209V6tfMYGqnId6lhM6R+VERAWYHp5/jGUrg/NhlIPiGf2TeTM9EAo2sHVHCxWPEz/WjX7+Fuwfb448FnlOg8rBVoa+oS2eXByQ+3mPhGXnehvR45r3gSugTKvuz03FD4IJzpULYzSdIuyEcPR4ErlU9vK3CkCtvLd2bpz1vk2kO9afyG4E7Fi5P2hCJG8M2S1ltRrJWyzp0vuO6s9PuSAHwhjqEZg1R2GWTsqd8dbxHX7oqbZq9rjQBaQTGLEMsev+SQYeMk/BaSIMcDTbSpC3MgTngyIk6aOa47izTk4qsAQKBgQDXu312WNNqI32iTpprKO5viGzKyB+TMzj6XpkeDkp+rq6ZTCIv5blvZFdEhdDtUbFzAYg1wVLib8I3/ID4qIV9xHaROzaWKW7WjaWd8EEwtje/D5YUDBmQBeZwczXlXbK5ZyXS4akotU74gFRlChEvF6YQbFye11+Ji5aIvfZ3gQKBgQDC5aUYAGXtF9ykbCgxwfNCH1dW8BR9u7ar8lUE42Ec9HJ7e9hripXKI4VTJmi4MMmYkxtG4Eg+IF7MB55QF1r4NNRCZ+imA8Tnxk8lMd105Y+6mJDfsnOkxH4ydeBW39bcwsCXUywdnMkpG46Pze8YMYPLv9gPm47ON58IKMQSOQKBgQCOqWsXdzgfyWaMjeRqFwBOe25OTzcqNcZpM2OYT6UNz2Cg+YrmF8mgEz/ujXuTZOGvBwVXXwf7vCI4ud9kELVubRxngDvh43ZrpfIu1rGVj/qfe6Qoj7Pb3Tr9hALRMjw9hSurIBWoWPXnOZ4Vzyl79eyYkcBSPmTsZYXf2ZeCgQKBgDWoOdKo0Wb8Cc/uwwYn6owKyuXxhQK0um8OcZ+95g+tsRMUHppE9kZHjz48Ndp3/BiYb4sM1nbcPJ0Zf9l3BKGPEd0SdHe4U+6np0SLPPgg93gc5s3feH0lZ8UGtPPV/naa26EN0fh5INzDbHVk8e2MPEfNEnQBlMhrgcoiRxDpAoGAXnBqa+zB6/Mh/GI20bLcPJb86+X5SdtKNBab12/InAiWhDiD/tB1BpGpNH5Ko07TKcijspdjFsKFdzsSK6ysUM56RM1DljBmTV/ZhpQ5cH0dJIZCCfNq0HMjMn7DIpHqO82mQcdVOjTYLVoEPUA8g4Q3qlbYNQ3UEr3pLTBNK9o=";
      byte[] keyData = Convert.FromBase64String(privateKey);

      var rsa = RSA.Create();
      rsa.ImportPkcs8PrivateKey(keyData, out _);
      byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
      return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));    
    }
  }
}

